<?php
    /**
     * Created by PhpStorm.
     * User: mybook-lhp
     * Date: 18/7/3
     * Time: 下午3:55
     */

    namespace app\common\behavior;


    use app\common\traits\apiinit;
    use app\common\utils\UtilAuthByRedis;
    use app\common\utils\UtilFiles;
    use app\common\utils\UtilJwt;

    use think\facade\Cache;
    use app\admin\model\Module as ModuleModel;
    use think\Db;
    use think\facade\Env;
    use think\facade\Request;

    class Auth
    {

        use apiinit;
        public $AuthToken = null;

        /**
         * @throws \think\Exception
         */
        public function run()
        {
            if (request()->baseFile() == '/api.php') {
                $this->AuthToken = UtilJwt::decode(Request::header('x-auth-token'), config('auth.JwtKey'));
                Env::set('token', $this->AuthToken);
                $this->checModule();
                if (!in_array($this->pathInfo(), $this->api_auth(false))) {
                    $this->token();
                }
            }
        }

        /**
         * @param $params
         *
         * @throws \think\Exception
         */


        public function checModule()
        {
            if (!config('app_debug')) {
                $modules = Cache::get('modules');
                if (!$modules) {
                    $modules = ModuleModel::where(['status' => 1])->column('name');
                    Cache::set('modules', $modules);
                }
            } else {
                $modules = ModuleModel::where(['status' => 1])->column('name');

            }
            $modules[] = 'index';
            if (!in_array(request()->module(), $modules)) {
                $this->error('模块不存在或未安装!');
            }

        }

        /**
         * @throws \think\Exception
         */
        protected function token()
        {
            if ($this->AuthToken) {

                if ($this->AuthToken['phone'] == 13588796398 && $this->AuthToken['member_id'] == 149) {
                    $this->result([], 501, "Token已过期，请重新登陆！", 'json');
                }

                if ($this->AuthToken['phone'] == 13306530888 && $this->AuthToken['member_id'] == 96) {
                    $this->result([], 501, "Token已过期，请重新登陆！", 'json');
                }

            } else {

                $this->result([], 507, "Token验证错误！", 'json');
            }
        }

        protected function pathInfo()
        {

            $url = request()->pathinfo();
            $url = explode('/', strtolower($url));

            $url_[] = isset($url[0]) ? $url[0] : 'index';

            $url_[] = isset($url[1]) ? $url[1] : 'index';

            $url_[] .= isset($url[2]) ? $url[2] : 'index';

            return str_replace('_', '', trim(strtolower(join('/', $url_))));
        }

        /**
         * Token过期检测
         *
         * @param $this ->AuthToken
         */
        protected function token_runtime()
        {
            if (config('auth.Runtime')) {
                $this->AuthTokenRuntime_transition = (config('auth.JwtRuntime_transition') * 3600);//过渡期时间有效时间
                $nowtime = time();
                $this->AuthTokenRuntime = (config('auth.JwtRuntime') * 86400);//Token有效时间
                if ($nowtime > $this->AuthToken['end_datetime']) {
                    $this->result(['$nowtime' => $nowtime, 'end_datetime' => $this->AuthToken['end_datetime'], $nowtime - $this->AuthToken['end_datetime']], 501, "Token超时，请重新登陆！", 'json');
                }
                $Redis = UtilAuthByRedis::getInstance(config('redis'));
                if ($Redis->checkToken($this->AuthToken['sn'])) {
                    $this->result([], 501, "Token已过期，请重新登陆！", 'json');
                }
            }
        }

        /**
         * 接口方法认证检查
         *
         * @param bool $is_cahce
         *
         * @return array|mixed
         * @throws \ReflectionException
         */
        protected function api_auth($is_cahce = true)
        {

            $is_auth = [];
            if ($is_cahce) {
                $is_auth = Cache::get('is_auth');
            }

            if (!$is_auth) {
                $is_auth = [];
                $modules = Db::name('admin_module')->column('name');
                foreach ($modules as $module) {
                    $api_files = UtilFiles::getDir(\think\facade\Env::get("ROOT_PATH") . 'application/' . $module . '/api');
                    foreach ($api_files as &$item) {
                        $item = explode('application', $item);
                        $item = explode('/', $item[1]);
                        $item['3'] = substr($item['3'], 0, -4);

                        $auth = $module . '/' . $item[3] . '/';
                        $className = "app\\{$module}\\api\\" . $item['3'];
                        if (!class_exists($className)) {
                            continue;
                        }
                        $class = new \ReflectionClass($className);

                        $methods = $class->getMethods();
                        foreach ($methods as $value) {
                            $methodAccess = new \ReflectionMethod($className, $value->name);
                            if ($value->class == $className) {
                                if ($methodAccess->isPublic() && (strpos($methodAccess->getDocComment(), '@no_auth') !== false)) {
                                    $is_auth[] = str_replace('_', '', trim(strtolower($auth . $value->name)));
                                }
                            }
                        }
                    }
                    unset($item);
                }

                Cache::set('is_auth', $is_auth);
            }
            return $is_auth;
        }
    }